package com.csust.automaticteach.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.csust.automaticteach.annotation.AuthCheck;
import com.csust.automaticteach.common.BaseResponse;
import com.csust.automaticteach.common.ResultUtils;
import com.csust.automaticteach.constant.UserAuthConstant;
import com.csust.automaticteach.exception.BusinessException;
import com.csust.automaticteach.exception.ErrorCode;
import com.csust.automaticteach.exception.ThrowUtils;
import com.csust.automaticteach.manager.verifyCode.MyCaptchaService;
import com.csust.automaticteach.model.dto.user.*;
import com.csust.automaticteach.model.entity.User;
import com.csust.automaticteach.model.vo.user.LoginUserVO;
import com.csust.automaticteach.model.vo.user.UserVO;
import com.csust.automaticteach.service.UserService;
import com.csust.opration.logger.annotation.LogOperation;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static com.csust.automaticteach.constant.SectionConstant.*;
import static com.csust.automaticteach.utils.EncryptUtils.getEncryptPassWord;
import static com.csust.opration.logger.constant.CommonConstant.*;

/**
 * @ClassNameUserController
 * @Description 用户控制层
 * @Author钰玟
 * @Date2025/4/10 下午8:42
 * @Version 1.0
 **/

@RestController
@RequestMapping("/user")
//@Tag(name = "用户相关接口")
public class UserController {

    @Resource
    private UserService userService;
    @Resource
    private CaptchaService captchaService;
    @Resource
    private MyCaptchaService myCaptchaService;
    /**
     * 用户注册
     *
     * @param userRegisterDTO 注册数据传输模型
     * @return 用户Id
     */
    @PostMapping("/register")
    public BaseResponse<Long> userRegister(@RequestBody UserRegisterDTO userRegisterDTO) {
        String userAccount = userRegisterDTO.getUserAccount();
        String userPassword = userRegisterDTO.getUserPassword();
        String userCheckPassword = userRegisterDTO.getCheckPassword();
        String userRole = userRegisterDTO.getUserRole();
        long result = userService.userRegister(userAccount, userPassword, userCheckPassword, userRole);
        return ResultUtils.success(result);
    }
    /**
     * 用户注册 数字验证码+滑动验证码
     *
     * @param userRegisterWithVerificationRequest 注册数据传输模型
     * @return 用户Id
     */
    @PostMapping("/register/verify")
    public BaseResponse<Long> userRegisterWithDoubleVerify(@RequestBody UserRegisterWithVerificationRequest userRegisterWithVerificationRequest
            ,HttpServletRequest request) {
        //1.校验参数
        ThrowUtils.throwIf(userRegisterWithVerificationRequest == null, ErrorCode.PARAMS_ERROR);
        //2.检验验证码
        //2.1 校验数字/字母验证码
        if(userRegisterWithVerificationRequest.getCaptcha() == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码不能为空");
        }
        boolean validated = myCaptchaService.validateCaptcha(request.getSession().getId(), userRegisterWithVerificationRequest.getCaptcha());
        if(!validated){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码输入错误");
        }
        //2.2 检验滑动验证码
        CaptchaVO captchaVO = new CaptchaVO();
        captchaVO.setCaptchaVerification(userRegisterWithVerificationRequest.getVerificationCode());
        ResponseModel verification = captchaService.verification(captchaVO);
        if (!verification.isSuccess()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证错误");
        }
        //3.进行注册用户
        String userAccount = userRegisterWithVerificationRequest.getUserAccount();
        String userPassword = userRegisterWithVerificationRequest.getUserPassword();
        String userCheckPassword = userRegisterWithVerificationRequest.getCheckPassword();
        String userRole = userRegisterWithVerificationRequest.getUserRole();
        long result = userService.userRegister(userAccount, userPassword, userCheckPassword, userRole);
        return ResultUtils.success(result);
    }
    /**
     * 用户登录 用于简化测试
     *
     * @param userLoginDTO 用户登录数据传输模型
     * @return 用户登录展示模型
     */
    @PostMapping("/login")
//    @LogOperation(menu = NEW_USER, type = ADD, content = "'用户注册:'+{#userRegisterDTO.userAccount}")
    public BaseResponse<LoginUserVO> userLogin(@RequestBody UserLoginDTO userLoginDTO, HttpServletRequest request) {
        ThrowUtils.throwIf(userLoginDTO == null, ErrorCode.PARAMS_ERROR);
        String userAccount = userLoginDTO.getUserAccount();
        String userPassword = userLoginDTO.getUserPassword();
        LoginUserVO userLoginVO = userService.userLogin(userAccount, userPassword, request);
        return ResultUtils.success(userLoginVO);
    }
    /**
     * 新用户登录 滑动验证码
     *
     * @param userLoginWithVerificationRequest 用户登录数据传输模型
     * @return 用户登录展示模型
     */
    @PostMapping("/login/verify")
//    @LogOperation(menu = NEW_USER, type = ADD, content = "'用户注册:'+{#userRegisterDTO.userAccount}")
    public BaseResponse<LoginUserVO> userLoginWithVerifyCode(@RequestBody UserLoginWithVerificationRequest userLoginWithVerificationRequest
            , HttpServletRequest request) {
        //1.校验参数
        ThrowUtils.throwIf(userLoginWithVerificationRequest == null, ErrorCode.PARAMS_ERROR);
        //2.提取相关字段
        String userAccount = userLoginWithVerificationRequest.getUserAccount();
        String userPassword = userLoginWithVerificationRequest.getUserPassword();
        String verificationCode = userLoginWithVerificationRequest.getVerificationCode();
        // 3.验证滑动验证码
        CaptchaVO captchaVO = new CaptchaVO();
        captchaVO.setCaptchaVerification(verificationCode);
        ResponseModel verification = captchaService.verification(captchaVO);
        //4.判断验证码是否正确
        if (!verification.isSuccess()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证错误");
        }
        //5.登录
        LoginUserVO userLoginVO = userService.userLogin(userAccount, userPassword, request);
        return ResultUtils.success(userLoginVO);
    }

    /**
     * 获取用户
     *
     * @param request request
     * @return loginVO
     */
    @GetMapping("/get/login")
    public BaseResponse<LoginUserVO> getLoginUser(HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        return ResultUtils.success(userService.getLoginUserVO(loginUser));
    }

    /**
     * 用户注销
     *
     * @param request 请求
     * @return boolean
     */
    @PostMapping("/logout")
    public BaseResponse<Boolean> userLogout(HttpServletRequest request) {
        ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR);
        Boolean result = userService.userLogout(request);
        return ResultUtils.success(result);
    }

    /**
     * 增加用户
     *
     * @param userAddDTO 增加用户的传输对象
     * @return long
     */
    @PostMapping("/add")
    @LogOperation(menu = USER_MANAGE, type = ADD, content = "'用户增加:'+{#userAddDTO.userAccount}")
    @AuthCheck(mustRole = UserAuthConstant.ADMIN_ROLE)
    public BaseResponse<Long> userAdd(@RequestBody UserAddDTO userAddDTO) {
        ThrowUtils.throwIf(userAddDTO == null, ErrorCode.PARAMS_ERROR);
        User user = new User();
        // 拷贝基本属性
        BeanUtil.copyProperties(userAddDTO, user);
        //赋值其他属性
        //默认密码
        String password = userAddDTO.getUserPassword();
        String encryptPassword = getEncryptPassWord("12345678");
        if(password != null) {
            encryptPassword = getEncryptPassWord(password);
        }
        user.setUserPassword(encryptPassword);
        boolean result = userService.save(user);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(user.getId());
    }

    /**
     * 查询用户
     *
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/get")
    @AuthCheck(mustRole = UserAuthConstant.ADMIN_ROLE)
    @LogOperation(menu = USER_MANAGE, type = VIEW, content = "'查询用户:'+{#id}")
    public BaseResponse<User> getUserById(@RequestParam("id") Long id) {
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        User user = userService.getById(id);
        ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR);
        return ResultUtils.success(user);
    }

    /**
     * 获取 脱敏用户
     *
     * @param id 用户id
     * @return 脱敏用户对象
     */
    @GetMapping("/get/vo")
    @AuthCheck(mustRole = UserAuthConstant.ADMIN_ROLE)
    @LogOperation(menu = USER_MANAGE, type = VIEW, content = "'查询用户VO:'+{#id}")
    public BaseResponse<UserVO> getUserVOById(@RequestParam("id") Long id) {
        BaseResponse<User> response = getUserById(id);
        User user = response.getData();
        return ResultUtils.success(userService.getUserVO(user));
    }

    /**
     * 更新用户
     */
    @PostMapping("/update")
    @AuthCheck(mustRole = UserAuthConstant.ADMIN_ROLE)
    @LogOperation(menu = USER_MANAGE, type = UPDATE, content = "'更新用户:'+{#userUpdateDTO.userAccount}")
    public BaseResponse<Boolean> updateUser(@RequestBody UserUpdateDTO userUpdateDTO) {
        if (userUpdateDTO == null || userUpdateDTO.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User user = new User();
        BeanUtils.copyProperties(userUpdateDTO, user);
        //默认密码
        String password = userUpdateDTO.getUserPassword();
        String encryptPassword = getEncryptPassWord("12345678");
        if(password != null) {
            encryptPassword = getEncryptPassWord(password);
        }
        user.setUserPassword(encryptPassword);
        boolean result = userService.updateById(user);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(true);
    }

    /**
     * 分页查询 获取分页用户列表
     *
     * @param userQueryDTO 查询DTO
     * @return
     */
    @PostMapping("/list/page/vo")
    @AuthCheck(mustRole = UserAuthConstant.ADMIN_ROLE)
    public BaseResponse<Page<UserVO>> listUserVOByPage(@RequestBody UserQueryDTO userQueryDTO) {
        ThrowUtils.throwIf(userQueryDTO == null, ErrorCode.PARAMS_ERROR);
        // 获取分页相关数据
        long current = userQueryDTO.getCurrent();
        long pageSize = userQueryDTO.getPageSize();
        //分页查询
        Page<User> userPage = userService.page(new Page<>(current, pageSize),
                userService.getUserQueryWrapper(userQueryDTO));
        Page<UserVO> userVOPage = new Page<>(current, pageSize, userPage.getTotal());
        List<UserVO> userVOList = userService.getUserVOList(userPage.getRecords());
        userVOPage.setRecords(userVOList);
        return ResultUtils.success(userVOPage);
    }

    /**
     * 根据id删除用户
     *
     * @param id 用户id
     * @return boolean
     */
    @PostMapping("/delete/{id}")
    @AuthCheck(mustRole = UserAuthConstant.ADMIN_ROLE)
    @LogOperation(menu = USER_MANAGE, type = DELETE, content = "'删除用户:'+{#id}")
    public BaseResponse<Boolean> deleteUser(@PathVariable("id") Long id) {
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        boolean result = userService.removeById(id);
        return ResultUtils.success(result);
    }
    /**
     * 批量删除用户
     *
     * @param idList 用户id列表
     * @return boolean
     */
    @PostMapping("/delete/batch")
    @AuthCheck(mustRole = UserAuthConstant.ADMIN_ROLE)
    @LogOperation(menu = USER_MANAGE, type = DELETE, content = "批量删除用户")
    public BaseResponse<Boolean> deleteBatchUser(List<Long> idList) {
        ThrowUtils.throwIf(CollUtil.isEmpty(idList), ErrorCode.PARAMS_ERROR);
        boolean result = userService.removeBatchByIds(idList);
        return ResultUtils.success(result);
    }


    @PostMapping("/forget/pwd")
    @LogOperation(menu = FORGET_PWD, type = EDIT, content = "'修改密码：+{#editForForgetPwdRequest.userAccount}'")
    public BaseResponse<Boolean> forgetPwd(@RequestBody EditForForgetPwdRequest editForForgetPwdRequest,HttpServletRequest request) {
        //参数校验
        ThrowUtils.throwIf(editForForgetPwdRequest == null, ErrorCode.PARAMS_ERROR);
        if(editForForgetPwdRequest.getCaptcha() == null ){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码不能为空");
        }
        boolean validated = myCaptchaService.validateCaptcha(request.getSession().getId(), editForForgetPwdRequest.getCaptcha());
        if(!validated){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "验证码输入错误");
        }
        //根据用户账号查询用户
        String userAccount= editForForgetPwdRequest.getUserAccount();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("userAccount",userAccount);
        User selectById = userService.getBaseMapper().selectOne(userQueryWrapper);
        ThrowUtils.throwIf(selectById == null, ErrorCode.NOT_FOUND_ERROR);
        //校验邮箱
        String selectByIdEmail = selectById.getEmail();
        ThrowUtils.throwIf(StrUtil.isBlank(selectByIdEmail), ErrorCode.OPERATION_ERROR,"用户邮箱不能为空");
        if(!selectByIdEmail.equals(editForForgetPwdRequest.getEmail())){
            ThrowUtils.throwIf(StrUtil.isBlank(selectByIdEmail), ErrorCode.OPERATION_ERROR,"用户邮箱错误");
        }
        //修改为默认密码
        String encryptPassword = getEncryptPassWord(userAccount + "123");
        selectById.setUserPassword(encryptPassword);
        boolean updateById = userService.updateById(selectById);
        ThrowUtils.throwIf(!updateById, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(updateById);
    }
}
